package session

import (
	"bytes"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"errors"
	"ktvserver/ktvutil"
	//"math/rand"
	"time"
)

const KTV_DOMAIN_TYPE_SRV = 0
const KTV_DOMAIN_TYPE_TXT = 1
const KTV_DOMAIN_TYPE_HOST = 2

// KEY
const KTV_SERVER_SECRET_CODE = "AFD4836712C5E77550897E25711E1D96"

const KTV_USER_SYNC_CODE = 0x2C94

type KtvUserInfo struct {
	StructLength uint16

	//BYTE  nDomainLength;
	//BYTE  nDomainType;
	//WORD  wPadding;
	CatID   byte
	Padding byte

	Speed   uint16 // 速度
	SynCode uint16 // 同步码, 用作校验

	CreateDate     uint32 // 创建时间
	ExpirationDate uint32 // 过期时间

}

// 返回结构体大小
func (info *KtvUserInfo) StructSize() int {
	return 16
}

// 是否已经过期
func (info *KtvUserInfo) IsExpired() bool {
	now := time.Now().Unix()
	if now > int64(info.ExpirationDate) || now < int64(info.CreateDate) {
		return true
	} else {
		return false
	}
}

//产生用户注册码
func GenUserLicense(userInfo KtvUserInfo, srvRecord string, secretCode string) (string, error) {

	// 结果
	strResult := ""

	/*

		// 先加密ktvuserinfo
		bufUserInfo := new(bytes.Buffer)
		binary.Write(bufUserInfo, binary.LittleEndian, userInfo)
		userInfoEncoded, err3 := BlowFishEncodeData(bufUserInfo.Bytes(), []bytes(secretCode)])
		if err3 != nil {
			return strResult, err3
		}


		// 创建加密缓冲区
		buf := new(bytes.Buffer)

		// 域名数据
		domainData := []byte(srvRecord)

		// 域名定义
		domainDef := make([]byte, 2)
		domainDef[0] = KTV_DOMAIN_TYPE_SRV
		domainDef[1] = byte(len(domainData))

		binary.Write(buf, binary.LittleEndian, randomNum)
		buf.Write(domainDef)
		buf.WriteByte(0)


		// 随机数作为加密的密钥
		randomNum := GetRamdomUint32()


		//

		//buflen := len(buf.Bytes())
		//outputlen := GetOutputSize(buflen)
		//fmt.Printf("buflen=%d, outputlen=%d\n", buflen, outputlen)

		//加密用户数据区域
		userSec, err3 := BlowFishEncodeData(buf.Bytes(), bfkey)
		if err3 != nil {
			return strResult, err3
		}

		hex.EncodeToString(userSec)
	*/

	return strResult, nil
}

// 产生用户注册码
func GenLocalUserLicense(userInfo KtvUserInfo, domainRecord string, domainType int, secretCode string) (string, error) {
	strNewLicense := ""

	return strNewLicense, nil
}

// 解密本地的用户注册码
func DecodeUserLicense(license string) (*KtvUserInfo, int, string, error) {
	return DecodeUserLicenseBySecret(license, KTV_SERVER_SECRET_CODE)
}

// 解密用户注册码
// license 必须为utf8编码的文字
func DecodeUserLicenseBySecret(license string, secretCode string) (*KtvUserInfo, int, string, error) {

	var userInfo *KtvUserInfo
	var domainType int
	var domainRecord string

	// 先将注册码转换为byte
	allData, err := hex.DecodeString(license)
	if err != nil {
		return userInfo, domainType, domainRecord, err
	}

	//fmt.Printf("allData len=%d, %s\n", len(allData), hex.EncodeToString(allData))

	userInfo = new(KtvUserInfo)
	domainType = 0

	// 检查长度是否足够, 是否超出1024, 是否为4的倍数
	nLength := len(allData)
	if nLength < userInfo.StructSize()+8 || nLength > 1024 || nLength%4 != 0 {
		return userInfo, domainType, domainRecord, errors.New("license length is wrong")
	}

	// HASH校验是否正确的代码
	sha1Result := sha1.Sum(allData[4:])
	isHashOK := true

	for i := 0; i < 4; i++ {
		if allData[i] != sha1Result[i] {
			isHashOK = false
			break
		}
	} // end for

	if isHashOK != true {
		return userInfo, domainType, domainRecord, errors.New("hash is wrong")
	}

	//
	beforeData := allData[8:]
	afterData, changedOK := BackByteOrder(beforeData)
	if changedOK != true {
		return userInfo, domainType, domainRecord, errors.New("Incorrect License length wrong")
	}

	// 解密数据
	randomKey := allData[4:8]
	//fmt.Printf("randomKey = %s\n", hex.EncodeToString(randomKey))
	decodedData, err2 := ktvutil.BlowFishDecodeData(afterData, randomKey)
	if err2 != nil {
		return userInfo, domainType, domainRecord, err2
	}

	// data
	// 检查域名的长度是否正确
	if decodedData[1] != testDomainLenght(decodedData[2:]) {
		return userInfo, domainType, domainRecord, errors.New("Incorrect domain")
	}

	/// 用户数据
	//
	offset := 2 + decodedData[1] + 1
	userInfoBytes, err4 := ktvutil.BlowFishDecodeData(decodedData[offset:], []byte(secretCode))
	if err4 != nil {
		return userInfo, domainType, domainRecord, err4
	}

	domainType = int(decodedData[0]) // 域名类型

	domainRecord = string(decodedData[2 : decodedData[1]+3])

	//
	rd := bytes.NewBuffer(userInfoBytes)
	binary.Read(rd, binary.LittleEndian, userInfo)

	// 校验解密的数据是否正确
	if userInfo.SynCode != KTV_USER_SYNC_CODE {
		return userInfo, domainType, domainRecord, errors.New("Sync Code Error")
	}

	// 调整参数
	AdjustUserInfo(license, userInfo)

	return userInfo, domainType, domainRecord, nil
}

// 测试域名的长度
func testDomainLenght(data []byte) byte {
	var dn byte

	dn = 0
	for i := 0; i < len(data); i++ {
		if data[i] != 0 {
			dn++
		} else {
			break
		}
	} // end for

	return dn
}

// 调换字节顺序
func ChangeByteOrder(src []byte) ([]byte, bool) {

	nLength := len(src)
	dst := make([]byte, nLength)

	if nLength%4 != 0 {
		return dst, false
	}

	nSize := nLength / 4

	for i := 0; i < 4; i++ {
		for j := 0; j < nSize; j++ {
			dst[i*nSize+j] = src[j*4+i]
		}
	}

	return dst, true
}

// 恢复字节顺序
func BackByteOrder(src []byte) ([]byte, bool) {
	nLength := len(src)
	dst := make([]byte, nLength)

	if nLength%4 != 0 {
		return dst, false
	}

	nSize := nLength / 4

	for i := 0; i < 4; i++ {
		for j := 0; j < nSize; j++ {
			dst[j*4+i] = src[i*nSize+j]
		}
	}

	return dst, true
}
